package gmodel

import (
	"context"
	"encoding/json"
	"time"

	"gitee.com/851537/gmodel/rds"
	"github.com/cloudwego/hertz/pkg/common/hlog"
)

// BaseRedisPubSub Redis发布订阅基类
type BaseRedisPubSub struct {
	BaseRedis
	client   *rds.Client
	pubSub   *rds.PubSubManager
	utils    *rds.PubSubUtils
	handlers map[string]rds.MessageHandler
	patterns map[string]rds.MessageHandler
}

// NewBaseRedisPubSub 创建新的Redis发布订阅基类实例
func NewBaseRedisPubSub() *BaseRedisPubSub {
	return &BaseRedisPubSub{
		handlers: make(map[string]rds.MessageHandler),
		patterns: make(map[string]rds.MessageHandler),
	}
}

// WithClient 设置Redis客户端
func (this *BaseRedisPubSub) WithClient(client *rds.Client) *BaseRedisPubSub {
	this.client = client
	this.pubSub = client.PubSub
	this.utils = rds.NewPubSubUtils(client)
	return this
}

// GetClient 获取Redis客户端
func (this *BaseRedisPubSub) GetClient() *rds.Client {
	return this.client
}

// GetPubSub 获取发布订阅管理器
func (this *BaseRedisPubSub) GetPubSub() *rds.PubSubManager {
	return this.pubSub
}

// GetUtils 获取发布订阅工具
func (this *BaseRedisPubSub) GetUtils() *rds.PubSubUtils {
	return this.utils
}

// Subscribe 订阅频道
func (this *BaseRedisPubSub) Subscribe(ctx context.Context, channel string, handler rds.MessageHandler) error {
	this.handlers[channel] = handler
	this.pubSub.AddHandler(channel, handler)
	return this.pubSub.Subscribe(ctx, channel)
}

// PSubscribe 模式订阅
func (this *BaseRedisPubSub) PSubscribe(ctx context.Context, pattern string, handler rds.MessageHandler) error {
	this.patterns[pattern] = handler
	this.pubSub.AddPatternHandler(pattern, handler)
	return this.pubSub.PSubscribe(ctx, pattern)
}

// Unsubscribe 取消订阅
func (this *BaseRedisPubSub) Unsubscribe(ctx context.Context, channels ...string) error {
	for _, channel := range channels {
		delete(this.handlers, channel)
		this.pubSub.RemoveHandler(channel)
	}
	return this.pubSub.Unsubscribe(ctx, channels...)
}

// PUnsubscribe 取消模式订阅
func (this *BaseRedisPubSub) PUnsubscribe(ctx context.Context, patterns ...string) error {
	for _, pattern := range patterns {
		delete(this.patterns, pattern)
		this.pubSub.RemovePatternHandler(pattern)
	}
	return this.pubSub.PUnsubscribe(ctx, patterns...)
}

// Publish 发布消息
func (this *BaseRedisPubSub) Publish(ctx context.Context, channel string, message interface{}) error {
	return this.pubSub.Publish(ctx, channel, message)
}

// PublishWithTTL 发布消息并设置过期时间
func (this *BaseRedisPubSub) PublishWithTTL(ctx context.Context, channel string, message interface{}, ttl time.Duration) error {
	return this.pubSub.PublishWithTTL(ctx, channel, message, ttl)
}

// PublishJSON 发布JSON消息
func (this *BaseRedisPubSub) PublishJSON(ctx context.Context, channel string, data interface{}) error {
	return this.utils.PublishJSON(ctx, channel, data)
}

// PublishJSONWithTTL 发布JSON消息并设置过期时间
func (this *BaseRedisPubSub) PublishJSONWithTTL(ctx context.Context, channel string, data interface{}, ttl time.Duration) error {
	return this.utils.PublishJSONWithTTL(ctx, channel, data, ttl)
}

// SubscribeWithJSONHandler 订阅并处理JSON消息
func (this *BaseRedisPubSub) SubscribeWithJSONHandler(ctx context.Context, channel string, handler func(ctx context.Context, data interface{}) error) error {
	return this.utils.SubscribeWithJSONHandler(ctx, channel, handler)
}

// SubscribeWithStructHandler 订阅并处理结构体消息
func (this *BaseRedisPubSub) SubscribeWithStructHandler(ctx context.Context, channel string, dataType interface{}, handler func(ctx context.Context, data interface{}) error) error {
	return this.utils.SubscribeWithStructHandler(ctx, channel, dataType, handler)
}

// PSubscribeWithJSONHandler 模式订阅并处理JSON消息
func (this *BaseRedisPubSub) PSubscribeWithJSONHandler(ctx context.Context, pattern string, handler func(ctx context.Context, channel string, data interface{}) error) error {
	return this.utils.PSubscribeWithJSONHandler(ctx, pattern, handler)
}

// PSubscribeWithStructHandler 模式订阅并处理结构体消息
func (this *BaseRedisPubSub) PSubscribeWithStructHandler(ctx context.Context, pattern string, dataType interface{}, handler func(ctx context.Context, channel string, data interface{}) error) error {
	return this.utils.PSubscribeWithStructHandler(ctx, pattern, dataType, handler)
}

// Broadcast 广播消息到多个频道
func (this *BaseRedisPubSub) Broadcast(ctx context.Context, channels []string, message interface{}) error {
	return this.utils.Broadcast(ctx, channels, message)
}

// BroadcastJSON 广播JSON消息到多个频道
func (this *BaseRedisPubSub) BroadcastJSON(ctx context.Context, channels []string, data interface{}) error {
	return this.utils.BroadcastJSON(ctx, channels, data)
}

// FanOut 扇出模式
func (this *BaseRedisPubSub) FanOut(ctx context.Context, sourceChannel string, targetChannels []string) error {
	return this.utils.FanOut(ctx, sourceChannel, targetChannels)
}

// FanOutJSON 扇出模式（JSON）
func (this *BaseRedisPubSub) FanOutJSON(ctx context.Context, sourceChannel string, targetChannels []string) error {
	return this.utils.FanOutJSON(ctx, sourceChannel, targetChannels)
}

// RetryPublish 重试发布消息
func (this *BaseRedisPubSub) RetryPublish(ctx context.Context, channel string, message interface{}, maxRetries int, retryDelay time.Duration) error {
	return this.utils.RetryPublish(ctx, channel, message, maxRetries, retryDelay)
}

// RetryPublishJSON 重试发布JSON消息
func (this *BaseRedisPubSub) RetryPublishJSON(ctx context.Context, channel string, data interface{}, maxRetries int, retryDelay time.Duration) error {
	return this.utils.RetryPublishJSON(ctx, channel, data, maxRetries, retryDelay)
}

// Close 关闭发布订阅
func (this *BaseRedisPubSub) Close() error {
	return this.pubSub.Close()
}

// IsClosed 检查是否已关闭
func (this *BaseRedisPubSub) IsClosed() bool {
	return this.pubSub.IsClosed()
}

// GetHandlers 获取所有频道处理器
func (this *BaseRedisPubSub) GetHandlers() map[string]rds.MessageHandler {
	return this.handlers
}

// GetPatterns 获取所有模式处理器
func (this *BaseRedisPubSub) GetPatterns() map[string]rds.MessageHandler {
	return this.patterns
}

// RemoveHandler 移除频道处理器
func (this *BaseRedisPubSub) RemoveHandler(channel string) {
	delete(this.handlers, channel)
	this.pubSub.RemoveHandler(channel)
}

// RemovePatternHandler 移除模式处理器
func (this *BaseRedisPubSub) RemovePatternHandler(pattern string) {
	delete(this.patterns, pattern)
	this.pubSub.RemovePatternHandler(pattern)
}

// ClearHandlers 清空所有处理器
func (this *BaseRedisPubSub) ClearHandlers() {
	this.handlers = make(map[string]rds.MessageHandler)
	this.patterns = make(map[string]rds.MessageHandler)
}

// LogMessage 记录消息日志
func (this *BaseRedisPubSub) LogMessage(msg *rds.Message) {
	hlog.Infof("Redis PubSub Message - Channel: %s, Pattern: %s, Payload: %s, ReceivedAt: %s",
		msg.Channel, msg.Pattern, msg.Payload, msg.ReceivedAt.Format(time.RFC3339))
}

// CreateDefaultHandler 创建默认的消息处理器
func (this *BaseRedisPubSub) CreateDefaultHandler() rds.MessageHandler {
	return func(ctx context.Context, msg *rds.Message) error {
		this.LogMessage(msg)
		return nil
	}
}

// CreateJSONHandler 创建JSON消息处理器
func (this *BaseRedisPubSub) CreateJSONHandler(handler func(ctx context.Context, data interface{}) error) rds.MessageHandler {
	return func(ctx context.Context, msg *rds.Message) error {
		var data interface{}
		if err := json.Unmarshal([]byte(msg.Payload), &data); err != nil {
			hlog.Errorf("unmarshal json error: %v", err)
			return err
		}
		return handler(ctx, data)
	}
}

// CreateStructHandler 创建结构体消息处理器
func (this *BaseRedisPubSub) CreateStructHandler(dataType interface{}, handler func(ctx context.Context, data interface{}) error) rds.MessageHandler {
	return func(ctx context.Context, msg *rds.Message) error {
		if err := json.Unmarshal([]byte(msg.Payload), dataType); err != nil {
			hlog.Errorf("unmarshal struct error: %v", err)
			return err
		}
		return handler(ctx, dataType)
	}
}
